package it.uni.bo.monitoring.sla.parser.slang;

import it.uni.bo.monitoring.sla.chain.availability.Reliability;
import it.uni.bo.monitoring.sla.chain.latency.Latency;
import it.uni.bo.monitoring.sla.chain.throughput.Throughput;
import it.uni.bo.monitoring.sla.parser.SlaBean;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;


import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class SlangBean extends SlaBean{

	private HashMap<String, String> slaMap;
	private HashMap<String, OperationSlang> operationMap;
	private HashMap<String, LatencySlang> latencyMap;
	private HashMap<String, ThroughputSlang> throughputMap;
	private HashMap<String, Double> durationMap;
	private HashMap<String, ReliabilitySlang> reliabilityMap;
	

	public void parse(byte[] b){
		try {
			SAXParserFactory factory = SAXParserFactory.newInstance();
			SAXParser saxParser = factory.newSAXParser();
			SlangHandler handler = new SlangHandler();
			InputStream inputStream = new ByteArrayInputStream(b);
			Reader reader = new InputStreamReader(inputStream,"UTF-8");
			InputSource is = new InputSource(reader);
			//is.setEncoding("UTF-8");
			saxParser.parse(is, handler);


			slaMap=handler.getSla();
			operationMap=handler.getOperation();
			latencyMap=handler.getLatency();
			throughputMap=handler.getThroughput();
			durationMap=handler.getDuration();
			reliabilityMap=handler.getReliability();
			//ralMap=getLatencyMap(handler.getLatency(), handler.getSla(), handler.getOperation(), handler.getDuration());
		} catch (IOException e) {
			l.error(e.getMessage());
		} catch (ParserConfigurationException e) {
			l.error(e.getMessage());
		} catch (SAXException e) {
			l.error(e.getMessage());
		}
	}
	
	public List<Throughput> getThroughputList() {
		List<Throughput> throughputList = new ArrayList<Throughput>();
		if((throughputMap!=null) && (slaMap!=null) && (durationMap!=null)){
			Iterator<String> keys = throughputMap.keySet().iterator();
			while(keys.hasNext()){
				String key = keys.next();
				ThroughputSlang ts = throughputMap.get(key);
				if(slaMap.containsKey(ts.getIdSla()) && durationMap.containsKey(ts.getIdWindow()))
					throughputList.add(new Throughput(ts.getConcurrency(), durationMap.get(ts.getIdWindow())));
			}
		}
		return throughputList;
	}
	
	public List<Latency> getLatencyList() {
		List<Latency> latencyList = new ArrayList<Latency>();
		if((latencyMap!=null) && (slaMap!=null) && (operationMap!=null) && (durationMap!=null)){
			Iterator<String> keysLatency = latencyMap.keySet().iterator();
			while(keysLatency.hasNext()){
				LatencySlang ls = latencyMap.get(keysLatency.next());
				if(slaMap.containsKey(ls.getIdSla()) && durationMap.containsKey(ls.getIdMaxDuration())){
					HashSet<String> operationsName= new HashSet<String>();
					List<String> idOperations = ls.getIdOperations();
					for(int i=0;i<idOperations.size();i++){
						if(operationMap.containsKey(idOperations.get(i)))
							operationsName.add(operationMap.get(idOperations.get(i)).getDescription());
					}
					latencyList.add(new Latency(operationsName, durationMap.get(ls.getIdMaxDuration())));
				}
			}
		}
		return latencyList;
	}

	@Override
	public List<Reliability> getReliabilityList() {
		List<Reliability> reliabilityList = new ArrayList<Reliability>();
		if((reliabilityMap!=null) && (slaMap!=null) && (durationMap!=null)){
			Iterator<String> keys = reliabilityMap.keySet().iterator();
			while(keys.hasNext()){
				String key = keys.next();
				ReliabilitySlang rs = reliabilityMap.get(key);
				if(slaMap.containsKey(rs.getIdSla()) && durationMap.containsKey(rs.getIdWindow()))
					reliabilityList.add(new Reliability(rs.getMaxFailures(), durationMap.get(rs.getIdWindow())));
			}
		}
		return reliabilityList;
	}


}
